using System;
using Firestarter.Test.Base;
using FireStarterModeller.BO;
using Habanero.Base;
using Habanero.BO;
using NUnit.Framework;

namespace FireStarterModeller.Test.BO
{
    [TestFixture]
    public class TestDMAssemblyDuplicateClassNameRule
    {
        [SetUp]
        public void SetupTest()
        {
            //Runs every time that any testmethod is executed
            TestUtilsDomain.SetupTest();
            BORegistry.DataAccessor = new DataAccessorInMemory();
        }

        [TestFixtureSetUp]
        public void TestFixtureSetup()
        {
            //Code that is executed before any test is run in this class. If multiple tests
            // are executed then it will still only be called once.
            TestUtilsDomain.SetupFixture();
        }

        [TearDown]
        public void TearDownTest()
        {
            //runs every time any testmethod is complete
        }

        #region TestDMAssemblyDuplicateClassName
        [Test]
        public void Test_CreateDMAssemblyDuplicateClassNameRule()
        {
            //---------------Set up test pack-------------------
            //---------------Assert Precondition----------------
            //---------------Execute Test ----------------------
            IBusinessObjectRule rule = new DMAssemblyDuplicateClassNameRule();
            //---------------Test Result -----------------------
            Assert.IsNotNull(rule);
            Assert.AreEqual("DMAssemblyDuplicateClassName", rule.Name);
            Assert.AreEqual(ErrorLevel.Error, rule.ErrorLevel);
        }

//        [Test]
//        public void Test_CreateDMAssemblyDuplicateClassNameRule_WhenAssemblyNull_ShouldRaiseError()
//        {
//            //---------------Set up test pack-------------------
//            //---------------Assert Precondition----------------
//            //---------------Execute Test ----------------------
//            try
//            {
//                new DMAssemblyDuplicateClassNameRule();
//                Assert.Fail("expected ArgumentNullException");
//            }
//            //---------------Test Result -----------------------
//            catch (ArgumentNullException ex)
//            {
//                StringAssert.Contains("Value cannot be null", ex.Message);
//                StringAssert.Contains("dmAssembly", ex.ParamName);
//            }
//        }


        [Test]
        public void Test_IsValid_WhenNoClasses_ShouldBeTrue()
        {
            //---------------Set up test pack-------------------
            DMAssembly dmAssembly = TestUtilsShared.CreateUnsavedValidProjectAssemblyInfo();
            IBusinessObjectRule rule = new DMAssemblyDuplicateClassNameRule();
            //---------------Assert Precondition----------------
            Assert.AreEqual(0, dmAssembly.Classes.Count);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(dmAssembly);
            //---------------Test Result -----------------------
            Assert.IsTrue(isValid);
        }

        [Test]
        public void Test_IsValid_True_WhenOneClass()
        {
            //---------------Set up test pack-------------------
            DMAssembly dmAssembly = TestUtilsShared.CreateUnsavedValidProjectAssemblyInfo();
            dmAssembly.Classes.CreateBusinessObject();
            IBusinessObjectRule rule = new DMAssemblyDuplicateClassNameRule();
            //---------------Assert Precondition----------------
            Assert.AreEqual(1, dmAssembly.Classes.Count);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(dmAssembly);
            //---------------Test Result -----------------------
            Assert.IsTrue(isValid);
        }

        [Test]
        public void Test_IsValid_False_WhenDuplicateClassName()
        {
            //---------------Set up test pack-------------------
            string className = TestUtilsShared.GetRandomString();
            DMAssembly dmAssembly = TestUtilsDMAssembly.CreateUnsavedDefaultDMAssembly();
            var dmClass1 = dmAssembly.CreateClass(className);
            var dmClass2 = dmAssembly.CreateClass(className);
            IBusinessObjectRule rule = new DMAssemblyDuplicateClassNameRule();
            //---------------Assert Precondition----------------
            Assert.AreEqual(2, dmAssembly.Classes.Count);
            Assert.AreEqual(dmClass1.ClassNameBO, dmClass2.ClassNameBO);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(dmAssembly);
            //---------------Test Result -----------------------
            Assert.IsFalse(isValid);
            StringAssert.Contains("The Assembly '", rule.Message);
            StringAssert.Contains("'" + dmAssembly.ToString() + "'", rule.Message);
            StringAssert.Contains("' cannot have more than one Class with the same name('", rule.Message);
        }

        [Test]
        public void Test_IsValid_True_WhenNoDuplicateClassName()
        {
            //---------------Set up test pack-------------------
            DMAssembly dmAssembly = TestUtilsDMAssembly.CreateUnsavedDefaultDMAssembly();
            DMClass dmClass = dmAssembly.Classes.CreateBusinessObject();
            DMClass dmClass2 = dmAssembly.Classes.CreateBusinessObject();
            string className = TestUtilsShared.GetRandomString();
            dmClass.ClassNameBO = className;
            dmClass2.ClassNameBO = className + "2";
            IBusinessObjectRule rule = new DMAssemblyDuplicateClassNameRule();
            //---------------Assert Precondition----------------
            Assert.AreNotEqual(dmClass.ClassNameBO, dmClass2.ClassNameBO);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(dmAssembly);
            //---------------Test Result -----------------------
            Assert.IsTrue(isValid);
        }

        [Test]
        public void Test_IsValid_True_WhenClassNameEmpty()
        {
            //---------------Set up test pack-------------------
            DMAssembly dmAssembly = TestUtilsDMAssembly.CreateUnsavedDefaultDMAssembly();
            DMClass dmClass = dmAssembly.Classes.CreateBusinessObject();
            DMClass dmClass2 = dmAssembly.Classes.CreateBusinessObject();
            string className = TestUtilsShared.GetRandomString();
            dmClass.ClassNameBO = "";
            dmClass2.ClassNameBO = className;
            IBusinessObjectRule rule = new DMAssemblyDuplicateClassNameRule();
            //---------------Assert Precondition----------------
            Assert.AreNotEqual(dmClass.ClassNameBO, dmClass2.ClassNameBO);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(dmAssembly);
            //---------------Test Result -----------------------
            Assert.IsTrue(isValid);
        }

        [Test]
        public void Test_IsValid_WhenDuplicateClassName_AlsoHasClassNameEmpty_ShouldBeFalse()
        {
            //---------------Set up test pack-------------------
            DMAssembly dmAssembly = TestUtilsDMAssembly.CreateUnsavedDefaultDMAssembly();
            DMClass dmClass = dmAssembly.Classes.CreateBusinessObject();
            DMClass dmClass2 = dmAssembly.Classes.CreateBusinessObject();
            DMClass dmClass3 = dmAssembly.Classes.CreateBusinessObject();
            string className = TestUtilsShared.GetRandomString();
            dmClass.ClassNameBO = className;
            dmClass2.ClassNameBO = className;
            IBusinessObjectRule rule = new DMAssemblyDuplicateClassNameRule();
            //---------------Assert Precondition----------------
            Assert.AreEqual(3, dmAssembly.Classes.Count);
            Assert.AreEqual(dmClass.ClassNameBO, dmClass2.ClassNameBO);
            Assert.AreNotEqual(dmClass.ClassNameBO, dmClass3.ClassNameBO);
            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(dmAssembly);
            //---------------Test Result -----------------------
            Assert.IsFalse(isValid);
            StringAssert.Contains("The Assembly '", rule.Message);
            StringAssert.Contains("'" + dmAssembly.ToString() + "'", rule.Message);
            StringAssert.Contains("' cannot have more than one Class with the same name('", rule.Message);
        }

        [Test]
        public void Test_IsValid_False_WhenManyDuplicateClassName()
        {
            //---------------Set up test pack-------------------
            DMAssembly dmAssembly = TestUtilsDMAssembly.CreateUnsavedDefaultDMAssembly();
            DMClass dmClass = dmAssembly.Classes.CreateBusinessObject();
            DMClass dmClass2 = dmAssembly.Classes.CreateBusinessObject();
            DMClass dmClass3 = dmAssembly.Classes.CreateBusinessObject();
            string className = TestUtilsShared.GetRandomString();
            dmClass.ClassNameBO = className;
            dmClass2.ClassNameBO = TestUtilsShared.GetRandomString();
            dmClass3.ClassNameBO = className;
            IBusinessObjectRule rule = new DMAssemblyDuplicateClassNameRule();
            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            bool isValid = rule.IsValid(dmAssembly);
            //---------------Test Result -----------------------
            Assert.IsFalse(isValid);
            StringAssert.Contains("The Assembly '", rule.Message);
            StringAssert.Contains("'" + dmAssembly.ToString() + "'", rule.Message);
            StringAssert.Contains("' cannot have more than one Class with the same name('", rule.Message);
        }

        #endregion
    }
}